import 'dart:async';
import 'dart:convert' as convert;

import 'package:amap_plugin/index.dart';
import 'package:amap_plugin/src/models/map_view_options.dart';
import 'package:amap_plugin/src/models/marker_options.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

typedef void AMapViewCreatedCallback(AMapViewController controller);
typedef void OnMapClick(LatLng latLng);
typedef void OnLocationChanged(LatLng latLng);

const String METHOD_CHANNEL_SET_MAX_ZOOM_LEVEL = "setMaxZoomLevel";
const String METHOD_CHANNEL_SET_MIN_ZOOM_LEVEL = "setMinZoomLevel";
const String METHOD_CHANNEL_ON_MAP_CHANGED = "onMapClick";
const String METHOD_CHANNEL_ADD_MARKER = "addMarker";
const String METHOD_CHANNEL_ADD_MARKERS = "addMarkers";
const  String METHOD_CHANNEL_ADD_MARKER_PIN = "addMarkerPin";
const String METHOD_CHANNEL_ON_LOCATION_CHANGED = "onLocationChanged";
const String METHOD_CHANNEL_GET_SCALE_PER_PIXEL="getScalePerPixel";

class AMapView extends StatefulWidget {
  final MapViewOptions mapViewOptions;
  final AMapViewCreatedCallback onAMapViewCreatedCallback;
  final OnMapClick onMapClick;
  final OnLocationChanged onLocationChanged;

  ///[mapViewOptions] 地图初始化选项
  ///[onAMapViewCreatedCallback] 地图初始化完成后回调
  const AMapView(
      {Key key,
      this.mapViewOptions,
      this.onAMapViewCreatedCallback,
      this.onMapClick,
      this.onLocationChanged})
      : super(key: key);

  @override
  _AMapViewState createState() => _AMapViewState();
}

class _AMapViewState extends State<AMapView> {
  final Completer<AMapViewController> _controller =
      Completer<AMapViewController>();

  void _onPlatformViewCreated(int id) {
    final AMapViewController controller = AMapViewController._(
        id, widget, this.widget.onMapClick, this.widget.onLocationChanged);
    _controller.complete(controller);
    if (this.widget.onAMapViewCreatedCallback != null) {
      this.widget.onAMapViewCreatedCallback(controller);
    }
  }

  int aMapViewId;

  ///创建参数
  Map<String, dynamic> createParam() {
    MapViewOptions options = MapViewOptions();
    if (this.widget.mapViewOptions != null) {
      options = this.widget.mapViewOptions;
    }
    var rev = new Map<String, dynamic>();
    rev["compassEnabled"] = options.compassEnabled;
    rev["logoPosition"] = options.logoPosition;
    rev["mapType"] = options.mapType;
    rev["rotateGesturesEnabled"] = options.rotateGesturesEnabled;
    rev["scaleControlsEnabled"] = options.scaleControlsEnabled;
    rev["scrollGesturesEnabled"] = options.scrollGesturesEnabled;
    rev["tiltGesturesEnabled"] = options.tiltGesturesEnabled;
    rev["zoomControlsEnabled"] = options.zoomControlsEnabled;
    rev["zoomGesturesEnabled"] = options.zoomGesturesEnabled;
    rev["zOrderOnTop"] = options.zOrderOnTop;
    rev["myLocationStyle_strokeColor"] = options.myLocationStyle.strokeColor;
    rev["myLocationStyle_strokeWidth"] = options.myLocationStyle.strokeWidth;
    rev["myLocationStyle_radiusFillColor"] =
        options.myLocationStyle.radiusFillColor;
    rev["isMyLocationEnabled"] = options.isMyLocationEnabled;
    rev["showMyLocation"] = options.showMyLocation;
    rev["myLocationButtonEnabled"] = options.myLocationButtonEnabled;
    rev["locationType"] = options.myLocationStyle.locationType;
    return rev;
  }

  @override
  Widget build(BuildContext context) {
    if (TargetPlatform.android == defaultTargetPlatform) {
      return AndroidView(
        viewType: "plugins.yanwc/amap_view",
        onPlatformViewCreated: _onPlatformViewCreated,
        creationParams: createParam(),
        creationParamsCodec: const StandardMessageCodec(),
      );
    } else if (defaultTargetPlatform == TargetPlatform.iOS) {
      return Text(
          //苹果插件待实现
          '$defaultTargetPlatform is not yet supported by the flutter_2d_amap plugin');
    }
  }
}

///控制器
class AMapViewController {
  static final String methodChannelNameMapView = "plugins.yanwc/amap_view_";
  static final String methodChannelLocation = "location";

  AMapViewController._(
    int id,
    this.aMapView,
    this._onMapClick,
    this._onLocationChanged,
  ) : _channel = MethodChannel('$methodChannelNameMapView$id') {
    _channel.setMethodCallHandler(_handleMethod);
  }

  AMapView aMapView;
  final MethodChannel _channel;
  final OnMapClick _onMapClick;
  final OnLocationChanged _onLocationChanged;

  ///Navtive回调实现
  Future<dynamic> _handleMethod(MethodCall call) async {
    switch (call.method) {
      case METHOD_CHANNEL_ON_MAP_CHANGED:
        if (this._onMapClick != null) {
          Map<String, dynamic> maps = convert.jsonDecode(call.arguments);
          this._onMapClick(LatLng(maps["lat"], maps["lng"]));
        }
        break;
      case METHOD_CHANNEL_ON_LOCATION_CHANGED:
        if (this._onLocationChanged != null) {
          var latLng = LatLng(call.arguments["lat"], call.arguments["lng"],
              speed: call.arguments["speed"]);
          this._onLocationChanged(latLng);
        }
        break;
    }
  }

  ///设置最大放大级别
  Future<void> setMaxZoomLevel(double zoomLevel) async {
    await this
        ._channel
        .invokeMethod(METHOD_CHANNEL_SET_MAX_ZOOM_LEVEL, zoomLevel);
  }

  ///设置最小放大级别
  Future<void> setMinZoomLevel(double zoomLevel) async {
    await this
        ._channel
        .invokeMethod(METHOD_CHANNEL_SET_MIN_ZOOM_LEVEL, zoomLevel);
  }

  ///添加marker,返回MarkerId,类型[String]
  Future<String> addMarker(MarkerOptions markerOptions) async {
    Map<String,dynamic> maps =  await markerOptions.getMap();
    return await this
        ._channel
        .invokeMethod(METHOD_CHANNEL_ADD_MARKER,maps);
  }

  ///添加大头针
  Future<String> addMarkerPin({BitmapDescriptor bitmapDescriptor}) async{
    if(bitmapDescriptor == null){
      bitmapDescriptor = BitmapDescriptor("images/purple_pin.png");
    }
    return await this._channel.invokeMethod(METHOD_CHANNEL_ADD_MARKER_PIN,await bitmapDescriptor.data);
  }

  ///批量添加Marker
  Future<List<String>> addMarkers(List<MarkerOptions> list,bool moveToCenter) async{
    if(list == null) return null;
    Map<String,Object> params = <String,Object>{
      "moveToCenter":moveToCenter,
      "list":list.map((options)=>options.getMap())
    };
    return await this._channel.invokeMethod(METHOD_CHANNEL_ADD_MARKERS,params);
  }

  ///获取比例尺数据。当前缩放级别下，地图上1像素点对应的长度，单位米。
  Future<double> getScalePerPixel() async{
    return await this._channel.invokeMethod(METHOD_CHANNEL_GET_SCALE_PER_PIXEL);
  }

  ///定位
  Future<void> location() async {
    return await _channel.invokeMethod(methodChannelLocation);
  }
}
